package com.hsy.swu.clouddb

import android.util.Log
import androidx.lifecycle.LifecycleCoroutineScope
import cn.leancloud.LCObject
import cn.leancloud.LCQuery
import cn.leancloud.types.LCNull
import com.hsy.swu.hsyutils.MActivityUtil
import com.hsy.swu.hsyutils.MLog
import com.kongzue.dialogx.dialogs.InputDialog
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Date
import java.util.TimeZone

class LeanCloudHelper private constructor() {
    companion object {
        private var instance: LeanCloudHelper? = null

        var tempIsNeedShowSubmitDialog = false // 临时变量，用于判断用户是否需要反馈
        var tempSubmission = "" // 临时变量，用于存储用户已 submit的内容

        fun getInstance(): LeanCloudHelper? {
            // 在 LeanCloud服务关闭的时候，管理员也能获得 instance用来操作是否打开
            if (instance == null) {
                synchronized(this) {
                    if (instance == null) {
                        instance = LeanCloudHelper()
                    }
                }
            }
            return instance
        }
    }

    /** 存对象 */
    fun saveObjectInBackground(
        className: String,
        putAttributes: (LCObject) -> LCObject,
        onErrorCallback: (Throwable) -> Unit = {},
        onNextCallback: (LCObject) -> Unit = {}
    ) {
        val lcObject = LCObject(className)
        putAttributes(lcObject).saveInBackground().subscribe(object : Observer<LCObject> {
            override fun onSubscribe(d: Disposable) {
            }

            override fun onError(e: Throwable) {
                Log.v("hsy111", "save onError -> $e")
                onErrorCallback(e)
            }

            override fun onComplete() {
            }

            override fun onNext(t: LCObject) {
                Log.v("hsy111", "onNext -> $t")
                onNextCallback(t)
            }
        })
    }

    /** 删除对象 */
    fun deleteObjectInBackground(
        className: String,
        objectId: String,
        onErrorCallback: (Throwable) -> Unit = {},
        onNextCallback: () -> Unit
    ) {
        val lcObject = LCObject.createWithoutData(className, objectId)
        lcObject.deleteInBackground().subscribe(object : Observer<LCNull> {
            override fun onSubscribe(d: Disposable) {
            }

            override fun onError(e: Throwable) {
                Log.v("hsy111", "delete onError -> $e")
                onErrorCallback(e)
            }

            override fun onComplete() {
            }

            override fun onNext(t: LCNull) {
                onNextCallback()
            }
        })
    }

    /** 更新对象 */
    fun updateObjectInBackground(
        className: String,
        objectId: String,
        onErrorCallback: (Throwable) -> Unit = {},
        updateAttributes: (LCObject) -> Unit,
        onNextCallback: () -> Unit = {}
    ) {
        val lcObject = LCObject.createWithoutData(className, objectId)
        updateAttributes(lcObject)
        saveObjectInBackground(
            className,
            { return@saveObjectInBackground lcObject },
            {
                Log.v("hsy111", "update onError -> $it")
                onErrorCallback(it)
            }, { onNextCallback() }
        )
    }

    /** 根据 id从 LeanCloud数据库中查询 object,有 id就直接用这个,根据属性查就用下面的 findObjectInBackground */
    fun <T> getObjectInBackGround(
        className: String,
        objectId: String,
        getAttributes: (LCObject) -> T
    ) {
        LCQuery<LCObject>(className).getInBackground(objectId)
            .subscribe(object : Observer<LCObject> {
                override fun onSubscribe(d: Disposable) {
                }

                override fun onError(e: Throwable) {
                    Log.v("hsy111", "getObject onError -> $e")
                }

                override fun onComplete() {
                }

                override fun onNext(lcObject: LCObject) {
                    getAttributes(lcObject)
                }
            })
    }

    /** 自定义查询条件查询 */
    fun findObjectInBackground(
        className: String,
        addQueryCondition: (LCQuery<LCObject>) -> Unit,
        onNextCallback: (List<LCObject>) -> Unit
    ) {
        val query = LCQuery<LCObject>(className)
        addQueryCondition(query)
        query.findInBackground().subscribe(object : Observer<List<LCObject>> {
            override fun onSubscribe(d: Disposable) {
            }

            override fun onError(e: Throwable) {
                Log.v("hsy111", "findByCondition onError -> $e")
            }

            override fun onComplete() {
            }

            override fun onNext(lcObjectList: List<LCObject>) {
                onNextCallback(lcObjectList)
            }
        })
    }

    /** 发表评论 */
    fun postComment(
        content: String,
        onErrorCallback: (Throwable) -> Unit = {},
        onNextCallback: (LCObject) -> Unit
    ) {
        saveObjectInBackground(
            "Comment",
            {
                it.put("commentatorId", MyUser.currentUser.objectId)
                it.put("commentatorNickName", MyUser.currentUser.nickName)
                it.put("content", content)
                return@saveObjectInBackground it
            },
            {
                Log.v("hsy111", "postComment onError -> $it")
                onErrorCallback(it)
            }, onNextCallback
        )
    }

    /** 点赞评论 */
    fun likeThisComment(
        comment: Comment,
        onErrorCallback: (Throwable) -> Unit,
        onNextCallback: () -> Unit
    ) {
        updateObjectInBackground(
            "Comment",
            comment.objectId,
            { onErrorCallback(it) },
            {
                it.put("likeCounts", "${comment.newLikeCounts!! + 1}")
                it.put(
                    "likeUsers",
                    "${comment.likeUsers},${MyUser.currentUser.objectId}-${MyUser.currentUser.nickName}"
                )
            }, onNextCallback
        )
    }

    /** 取消点赞评论 */
    fun cancelLikeThisComment(
        comment: Comment,
        onErrorCallback: (Throwable) -> Unit,
        onNextCallback: () -> Unit
    ) {
        updateObjectInBackground(
            "Comment",
            comment.objectId,
            { onErrorCallback(it) },
            {
                it.put("likeCounts", "${comment.newLikeCounts!! - 1}")
                it.put(
                    "likeUsers",
                    comment.likeUsers.replace(
                        ",${MyUser.currentUser.objectId}-${MyUser.currentUser.nickName}",
                        ""
                    )
                )
            }, onNextCallback
        )
    }

    /** 解析时间戳 */
    fun parseTimeStamp(timeStamp: Long): String {
        val dateFormat = SimpleDateFormat("MM/dd\nHH:mm:ss")
        val date = Date(timeStamp)
        return dateFormat.format(date)
    }

    /** 解析 createAt和 updateAt */
    fun parseUpdateAt(updateAt: String): String {
        if (updateAt == "") return ""
        val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
        val outputFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
        inputFormat.timeZone = TimeZone.getTimeZone("UTC") // 设置输入时间的时区为UTC
        outputFormat.timeZone = TimeZone.getTimeZone("Asia/Shanghai") // 设置输出时间的时区为北京时间

        return try {
            val utcDate = inputFormat.parse(updateAt)
            val localTime = outputFormat.format(utcDate)
            localTime
        } catch (e: Exception) {
            e.printStackTrace()
            ""
        }
    }

    fun showSubmitDialog(
        lifecycleCoroutineScope: LifecycleCoroutineScope,
    ) {
        InputDialog.build()
            .setTitle("有什么 UI 方面的建议吗❓\n或者\n想对开发者说点什么❓\n都可以写在下面")
            .setCancelButton("暂时没有") { _, _, _ ->
                getInstance()?.updateObjectInBackground(
                    "MyUser",
                    MyUser.currentUser.objectId,
                    { MLog.attention("submission更新失败：$it") },
                    { it.put("submission", "") }
                )
                return@setCancelButton false
            }
            .setOkButton("提交") { dialog, _, inputStr ->
                if (inputStr.isEmpty()) {
                    MActivityUtil.showToast("请先输入")
                } else {
                    getInstance()?.updateObjectInBackground(
                        "MyUser",
                        MyUser.currentUser.objectId,
                        { MLog.attention("submission更新失败：$it") },
                        { it.put("submission", "${tempSubmission}-|-$inputStr") }
                    ) {
                        lifecycleCoroutineScope.launch {
                            MActivityUtil.showToast("上传成功")
                            dialog.dismiss()
                        }
                    }
                }
                return@setOkButton true
            }
            .show()
    }
}